﻿Imports Co9320.NamaAlert.Model
Imports System.Windows.Media
Imports System.Windows
Imports System.Windows.Media.Imaging
Imports System.Windows.Markup

Namespace Extension

    Public Class PluginWrapper

        Private FullName As String
        Private WithEvents Instance As IPlugin

        Private _Path As String
        Public ReadOnly Property Path() As String
            Get
                Return _Path
            End Get
        End Property

        Public Sub New(ByVal path As String)
            _Path = path

            If Not System.IO.File.Exists(Me.Path) Then
                OnSendSystemMessage(New SystemMessageEventArgs(SystemMessageKind.Error, "ファイルが見つかりません。" & Me.Path))
                Exit Sub
            End If

            Dim asm = System.Reflection.Assembly.LoadFrom(path)
            Dim type As Type = Nothing

            For Each t In asm.GetTypes
                If t.IsClass AndAlso t.IsPublic AndAlso Not t.IsAbstract AndAlso _
                   t.GetInterface("IPlugin") IsNot Nothing AndAlso _
                   t.GetCustomAttributes(GetType(PluginAttribute), True).Count > 0 Then
                    FullName = t.FullName
                    type = t
                    Exit For
                End If
            Next

            Attribute = DirectCast(type.GetCustomAttributes(GetType(PluginAttribute), True).First, PluginAttribute)
            ConstructProperties()
        End Sub

        Private Sub ConstructProperties()
            Const uriFormat As String = "pack://application:,,,/{0};component/{1}"

            Try
                Dim dic = New ResourceDictionary()
                Dim name = System.IO.Path.GetFileNameWithoutExtension(Me.Path)
                dic.Source = New Uri(String.Format(System.Globalization.CultureInfo.InvariantCulture, uriFormat, name, "Resources.xaml"))

                ' Name
                _Name = TryConvert(dic, "Name")
                If _Name = "" Then
                    OnSendSystemMessage(New SystemMessageEventArgs(SystemMessageKind.Error, "プラグイン" & name & "に適切なリソースが含まれていません。"))
                End If

                ' Description
                _Description = TryConvert(dic, "Description")

                ' ContextMenuHeader
                _ContextMenuHeader = TryConvert(dic, "ContextMenuHeader")

                ' Icons
                Dim path As String

                ' SmallIconPath
                path = TryConvert(dic, "SmallIconPath")
                If path IsNot Nothing Then
                    _SmallIcon = New BitmapImage(New Uri(String.Format(System.Globalization.CultureInfo.InvariantCulture, uriFormat, name, path)))
                End If

                ' LargeIconPath
                path = TryConvert(dic, "LargeIconPath")
                If path IsNot Nothing Then
                    _SmallIcon = New BitmapImage(New Uri(String.Format(System.Globalization.CultureInfo.InvariantCulture, uriFormat, name, path)))
                End If

            Catch ex As Exception
                Debug.Assert(False) ' Stop
            End Try
        End Sub

        Private Shared Function TryConvert(ByVal dic As ResourceDictionary, ByVal key As String) As String
            Try
                If dic.Contains(key) AndAlso dic(key) IsNot Nothing Then
                    Return CStr(dic(key)).Trim
                End If
            Catch ex As XamlParseException
                ' Do nothing
            End Try
            Return Nothing
        End Function

        Public Sub CreateInstance()
            If Instance IsNot Nothing Then
                Exit Sub
            End If

            If Not System.IO.File.Exists(Me.Path) Then
                OnSendSystemMessage(New SystemMessageEventArgs(SystemMessageKind.Error, "ファイルが見つかりません。" & Me.Path))
                Exit Sub
            End If

            Try
                Dim asm = System.Reflection.Assembly.LoadFrom(Me.Path)
                Instance = DirectCast(asm.CreateInstance(FullName), IPlugin)
            Catch ex As Exception
                Debug.Assert(False) ' Stop
            End Try
        End Sub

#Region "Methods wrapper"

        Public Sub Initialize(ByVal settings As IPluginSettings)
            If Instance Is Nothing Then
                Exit Sub
            End If
            Instance.Initialize(settings)
        End Sub

        Public Sub EditOptions(ByVal dialogOwner As Window)
            If Instance Is Nothing OrElse Not Me.HasEditableOptions Then
                Exit Sub
            End If
            Instance.EditOptions(dialogOwner)
        End Sub

        Public Sub ExecuteAlert(ByVal program As Model.LiveProgram)
            If Instance Is Nothing OrElse Not Me.HasAlertFunction Then
                Exit Sub
            End If
            Instance.ExecuteAlert(program)
        End Sub

        Public Sub ExecuteAction(ByVal program As Model.LiveProgram)
            If Instance Is Nothing OrElse Not Me.HasProgramAction Then
                Exit Sub
            End If
            Instance.ExecuteAction(program)
        End Sub

        Public Sub ExecuteWhenLiveProgramStarted(ByVal liveProgram As Model.LiveProgram)
            If Instance Is Nothing OrElse Me.RequireLiveProgramNotify = LiveProgramNotify.None Then
                Exit Sub
            End If
            Instance.ExecuteWhenLiveProgramStarted(liveProgram)
        End Sub

#End Region

#Region "Attribute wrapper"

        Private Attribute As PluginAttribute

        Public ReadOnly Property Guid() As Guid
            Get
                Return If(Attribute IsNot Nothing, Attribute.Guid, Nothing)
            End Get
        End Property

        Public ReadOnly Property RequireLiveProgramNotify() As LiveProgramNotify
            Get
                Return If(Attribute IsNot Nothing, Attribute.RequireLiveProgramNotify, LiveProgramNotify.None)
            End Get
        End Property

        Public ReadOnly Property HasProgramAction() As Boolean
            Get
                Return If(Attribute IsNot Nothing, Attribute.HasProgramAction, False)
            End Get
        End Property

        Public ReadOnly Property HasAlertFunction() As Boolean
            Get
                Return If(Attribute IsNot Nothing, Attribute.HasAlertFunction, False)
            End Get
        End Property

        Public ReadOnly Property HasEditableOptions() As Boolean
            Get
                Return If(Attribute IsNot Nothing, Attribute.HasEditableOptions, False)
            End Get
        End Property

        Public ReadOnly Property PublisherUrl() As String
            Get
                Return If(Attribute IsNot Nothing, Attribute.PublisherUrl, Nothing)
            End Get
        End Property

#End Region

#Region "Properties by resources"

        Private _Name As String
        Public ReadOnly Property Name() As String
            Get
                Return _Name
            End Get
        End Property

        Private _Description As String
        Public ReadOnly Property Description() As String
            Get
                Return _Description
            End Get
        End Property

        Private _ContextMenuHeader As String
        Public ReadOnly Property ContextMenuHeader() As String
            Get
                Return _ContextMenuHeader
            End Get
        End Property

        Private _SmallIcon As ImageSource
        Public ReadOnly Property SmallIcon() As ImageSource
            Get
                Return _SmallIcon
            End Get
        End Property

        Private _LargeIcon As ImageSource
        Public ReadOnly Property LargeIcon() As ImageSource
            Get
                Return _LargeIcon
            End Get
        End Property

#End Region

#Region "Events"

        Public Event RequestShowBalloonTip As EventHandler(Of ShowBalloonTipEventArgs)
        Protected Overridable Sub OnRequestShowBalloonTip(ByVal e As ShowBalloonTipEventArgs)
            RaiseEvent RequestShowBalloonTip(Me, e)
        End Sub

        Public Event RequestShowAlertWindow As EventHandler(Of ShowAlertWindowEventArgs)
        Protected Overridable Sub OnRequestShowAlertWindow(ByVal e As ShowAlertWindowEventArgs)
            RaiseEvent RequestShowAlertWindow(Me, e)
        End Sub

        Public Event RequestOpenUri As EventHandler(Of OpenUriEventArgs)
        Protected Overridable Sub OnRequestOpenUri(ByVal e As OpenUriEventArgs)
            RaiseEvent RequestOpenUri(Me, e)
        End Sub

        Public Event SendSystemMessage As EventHandler(Of Model.SystemMessageEventArgs)
        Protected Overridable Sub OnSendSystemMessage(ByVal e As SystemMessageEventArgs)
            RaiseEvent SendSystemMessage(Me, e)
        End Sub

        Private Sub Instance_RequestOpenUri(ByVal sender As Object, ByVal e As OpenUriEventArgs) Handles Instance.RequestOpenUri
            OnRequestOpenUri(e)
        End Sub

        Private Sub Instance_RequestShowAlertWindow(ByVal sender As Object, ByVal e As ShowAlertWindowEventArgs) Handles Instance.RequestShowAlertWindow
            OnRequestShowAlertWindow(e)
        End Sub

        Private Sub Instance_RequestShowBalloonTip(ByVal sender As Object, ByVal e As ShowBalloonTipEventArgs) Handles Instance.RequestShowBalloonTip
            OnRequestShowBalloonTip(e)
        End Sub

        Private Sub Instance_SendSystemMessage(ByVal sender As Object, ByVal e As Model.SystemMessageEventArgs) Handles Instance.SendSystemMessage
            OnSendSystemMessage(e)
        End Sub

#End Region

    End Class

End Namespace
